package com.enjoyor.health.HGPT.web.rest;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.ByteUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.enjoyor.health.HGPT.core.config.WxAppConfig;
import com.enjoyor.health.HGPT.core.entity.UserInfo;
import com.enjoyor.health.HGPT.core.entity.UserInfoMiniapp;
import com.enjoyor.health.HGPT.core.entity.UserInfoMiniappSession;
import com.enjoyor.health.HGPT.service.BizUserService;
import com.enjoyor.health.HGPT.util.EncryptUtil;
import com.enjoyor.health.HGPT.util.HttpClientSslUtils;
import com.enjoyor.health.HGPT.util.JsonUtil;
import com.enjoyor.health.HGPT.web.CodeEnum;
import com.enjoyor.health.HGPT.web.RetResult;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import java.util.Objects;

/**
 * 小程序用户相关接口
 * @author Zhu Min
 * @date 2023/10/18 9:23
 */
@Api(value = "用户", tags = {"用户注册登录管理"})
@Slf4j
@RestController
public class UserController {

    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private WxAppConfig wxAppConfig;
    @Autowired
    private BizUserService bizUserService;


    /**
     * 微信小程序登录接口,前端从微信获取的临时登录凭证
     */
    @RequestMapping(value = "/aiHealthReport/userLogin", method = { RequestMethod.GET, RequestMethod.POST })
    public RetResult WxLogin(String code){
        if (StringUtils.isBlank(code)) {
            return new RetResult().of(CodeEnum.MISS_CODE);
        }

        if (!wxMaService.switchover(wxAppConfig.getAppId())) {
            log.error("未找到对应appid={}的配置，请核实！", wxAppConfig.getAppId());
            return new RetResult().of(CodeEnum.MISS_APPID);
        }

        try {
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
            log.info(session.getSessionKey());
            log.info(session.getOpenid());

            if (StringUtils.isNotBlank(session.getOpenid())){
                Map<String, Object> payload = Maps.newHashMap();
                payload.put("openid", session.getOpenid());
                payload.put("session_key", session.getSessionKey());
                String tokenKey = wxAppConfig.getTokenKey();
                JWTSigner signer = JWTSignerUtil.hs256(tokenKey.getBytes());
                String jwtToken = JWTUtil.createToken(payload, signer);
                bizUserService.getOpenIdSession(session.getOpenid(), session.getSessionKey(), jwtToken);
                //获取手机号码
                String phone = bizUserService.getOpenIdPhone(session.getOpenid());

                    JSONObject result = new JSONObject();
                    result.put("openId", session.getOpenid());
                    result.put("token", jwtToken);
                    result.put("phone", phone);
                    if (StringUtils.isNotBlank(phone) && phone.length() == 11) {
                        result.put("register", 1);
                    }else {
                        result.put("register", 0);
                    }
                    RetResult retResult = new RetResult().of(CodeEnum.SUCCESS);
                    retResult.setResult(result);
                    return retResult;

            }else {
                log.error("/aiHealthReport/userLogin接口收：未获取到用户信息");
                return new RetResult().of(CodeEnum.NO_USER_INFO);
            }

        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            JSONObject o = new JSONObject();
            o.put("errMsg", e.getMessage());
            return new RetResult(CodeEnum.SERVER_EXCEPTION).setResult(o);
        }
    }

    /**
     * 用户小程序上注册
     */
    @RequestMapping(value = "/aiHealthReport/register", method = { RequestMethod.GET, RequestMethod.POST })
    public RetResult miniAppRegister(String name, String gender, String idNumber, String height, String weight, String phone, String openId){
        try {
            String userId = new String(EncryptUtil.encrypt(phone.getBytes(), wxAppConfig.getUserIdKey().getBytes()));
            UserInfo userInfo = new UserInfo();
            userInfo.setId(userId);
            userInfo.setName(name);
            userInfo.setPhone(phone);
            userInfo.setIdNumber(idNumber);
            userInfo.setGender("1".equalsIgnoreCase(gender)?1:0);
            if (StringUtils.isNotBlank(idNumber)){
                userInfo.setAge(ByteUtil.intToByte(IdcardUtil.getAgeByIdCard(idNumber)));
            }
            userInfo.setHeight(height);
            userInfo.setWeight(weight);

            UserInfoMiniapp userInfoMiniapp = new UserInfoMiniapp();
            userInfoMiniapp.setOpenId(openId);
            userInfoMiniapp.setPhone(phone);
            userInfoMiniapp.setUserId(userId);
            bizUserService.regUser(userInfo, userInfoMiniapp);
            return new RetResult().of(CodeEnum.SUCCESS);
        }catch (Exception e){
            log.error("注册出错", e);
            return new RetResult().of(CodeEnum.SERVER_EXCEPTION);
        }
    }

    /**
     * 获取手机号
     */
    @RequestMapping(value = "/aiHealthReport/userInfoPhone", method = { RequestMethod.GET, RequestMethod.POST })
    public RetResult getUserInfoPhone(String code){
        JSONObject wxJson;
        // 获取token
        String token_url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", wxAppConfig.getAppId(), wxAppConfig.getAppSecret());

        try {
            JSONObject token = JSON.parseObject(HttpClientSslUtils.doGet(token_url));
            if (token == null) {
                log.info("获取token失败");
                JSONObject result = new JSONObject();
                result.put("phone", "");
                RetResult retResult = new RetResult().of(CodeEnum.WX_TOKEN_FAILED);
                retResult.setResult(result);
                return retResult;
            }
            String accessToken = token.getString("access_token");
            if (StringUtils.isEmpty(accessToken)) {
                log.info("获取token失败");
                JSONObject result = new JSONObject();
                result.put("phone", "");
                RetResult retResult = new RetResult().of(CodeEnum.WX_TOKEN_FAILED);
                retResult.setResult(result);
                return retResult;
            }
            log.info("token : {}", accessToken);
            //获取phone
            String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"
                    + "?access_token=" + accessToken;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", code);
            String reqJsonStr = JsonUtil.objToString(jsonObject);
            wxJson = JSON.parseObject(HttpClientSslUtils.doPost(url, reqJsonStr));
            if (wxJson == null) {
                log.info("获取手机号失败");
                JSONObject result = new JSONObject();
                result.put("phone", "");
                RetResult retResult = new RetResult().of(CodeEnum.BUSY);
                retResult.setResult(result);
                return retResult;
            }
            int errorCode = wxJson.getInteger("errcode");
            log.info("errcode : {}", errorCode);
            if (errorCode == 0){
                String phoneNumber = wxJson.getJSONObject("phone_info")
                        .getString("purePhoneNumber");
                JSONObject result = new JSONObject();
                result.put("phone", phoneNumber);
                RetResult retResult = new RetResult().of(CodeEnum.SUCCESS);
                retResult.setResult(result);
                return retResult;
            }else if (errorCode == -1){
                JSONObject result = new JSONObject();
                result.put("phone", "");
                RetResult retResult = new RetResult().of(CodeEnum.BUSY);
                retResult.setResult(result);
                return retResult;
            }else if (errorCode == 40029){
                JSONObject result = new JSONObject();
                result.put("phone", "");
                RetResult retResult = new RetResult().of(CodeEnum.JS_CODE_ERROR);
                retResult.setResult(result);
                return retResult;
            }else {
                JSONObject result = new JSONObject();
                result.put("phone", "");
                RetResult retResult = new RetResult().of(CodeEnum.BUSY);
                retResult.setResult(result);
                return retResult;

            }
        } catch (Exception e) {
           log.error("获取手机号码出错", e);
            JSONObject result = new JSONObject();
            result.put("phone", "");
            RetResult retResult = new RetResult().of(CodeEnum.SERVER_EXCEPTION);
            retResult.setResult(result);
            return retResult;
        }
    }


    /**
     * 检测登陆状态
     */
    @RequestMapping(value = "/aiHealthReport/checkLogin", method = { RequestMethod.GET, RequestMethod.POST })
    public RetResult miniappToken(String token, String openId){
        UserInfoMiniappSession userInfoMiniappSession = bizUserService.getDbToken(openId);
        int effective = 0;
        if (userInfoMiniappSession != null){
            String storeToken = userInfoMiniappSession.getToken();
            if (StringUtils.isNotBlank(storeToken) && storeToken.equals(token)){
                effective = 1;
                log.info("checkLogin_app验证成功：{}", storeToken);
            }else {
                effective = 0;
                log.info("checkLogin_app验证失败：{}", storeToken);
            }
        }
        String phone = bizUserService.getOpenIdPhone(openId);
        JSONObject result = new JSONObject();
        result.put("effective", effective);
        result.put("phone", phone);
        result.put("register", (StringUtils.isNotBlank(phone) && phone.length()==11)? 1 :0);
        RetResult retResult =  new RetResult().of(CodeEnum.SUCCESS);
        retResult.setResult(result);
        return retResult;
    }

    /**
     * 修改信息
     */
    @RequestMapping(value = "/aiHealthReport/userInfoModify", method = { RequestMethod.GET, RequestMethod.POST })
    public RetResult updateUserInfo(String openId, String name, String height, String weight){
        bizUserService.updateUserInfo(openId, name, height, weight);
        return new RetResult().of(CodeEnum.SUCCESS);
    }

    /**
     * 验证码，前端返回open_id和phone
     */
    @RequestMapping(value = "/aiHealthReport/captcha", method = { RequestMethod.GET, RequestMethod.POST })
    public RetResult captcha(String openId, String captcha){
        if (StringUtils.isBlank(openId)){
            JSONObject result = new JSONObject();
            result.put("available", 0);
            return new RetResult().of(CodeEnum.ERROR).setResult(result);
        }

        String userIdKey = wxAppConfig.getUserIdKey();
        String userId = new String(Objects.requireNonNull(EncryptUtil.encrypt(captcha.getBytes(), userIdKey.getBytes())));

        JSONObject result = new JSONObject();
        result.put("available", bizUserService.captcha(captcha, userId, openId));
        return new RetResult().of(CodeEnum.SUCCESS).setResult(result);
    }

}
